﻿namespace CommonData.Data.Core.SQLCore
{
    using CommonData.Data.Core;
    using CommonData.Entity;
    using CommonData.Model.Core;
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.SqlClient;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Text;

    public class SqlFactory : IDbFactory, IDisposable
    {
        private SqlDbType ConvertType(DataType type)
        {
            SqlDbType bigInt = SqlDbType.BigInt;
            switch (type)
            {
                case DataType.Bigint:
                    return SqlDbType.BigInt;

                case DataType.Int:
                    return SqlDbType.Int;

                case DataType.Smallint:
                    return SqlDbType.SmallInt;

                case DataType.Tinyint:
                    return SqlDbType.TinyInt;

                case DataType.Bit:
                    return SqlDbType.Bit;

                case DataType.Decimal:
                    return SqlDbType.Decimal;

                case DataType.Numeric:
                    return SqlDbType.Decimal;

                case DataType.Money:
                    return SqlDbType.Money;

                case DataType.Smallmoney:
                    return SqlDbType.SmallMoney;

                case DataType.Float:
                    return SqlDbType.Float;

                case DataType.Real:
                    return SqlDbType.Float;

                case DataType.Datetime:
                    return SqlDbType.DateTime;

                case DataType.Smalldatetime:
                    return SqlDbType.SmallDateTime;

                case DataType.Char:
                    return SqlDbType.Char;

                case DataType.Varchar:
                    return SqlDbType.VarChar;

                case DataType.Text:
                    return SqlDbType.Text;

                case DataType.Nchar:
                    return SqlDbType.NChar;

                case DataType.Nvarchar:
                    return SqlDbType.NVarChar;

                case DataType.Ntext:
                    return SqlDbType.NText;

                case DataType.Binary:
                    return SqlDbType.Binary;

                case DataType.Varbinary:
                    return SqlDbType.VarBinary;

                case DataType.Image:
                    return SqlDbType.Image;

                case DataType.Timestamp:
                    return SqlDbType.Timestamp;

                case DataType.Uniqueidentifier:
                    return SqlDbType.UniqueIdentifier;

                case DataType.Variant:
                    return SqlDbType.Variant;
            }
            return bigInt;
        }

        public string CreateConverageSql(Type type, Converage converage)
        {
            StringBuilder builder = new StringBuilder();
            if (Converage.Count == converage)
            {
                builder.AppendFormat("select count() from {0}", EntityTypeCache.GetTableInfo(type).Table.Name);
            }
            else if (Converage.CountNotNll == converage)
            {
                builder.AppendFormat("select count(*) from {0}", EntityTypeCache.GetTableInfo(type).Table.Name);
            }
            return builder.ToString();
        }

        public string CreateConverageSql(Type type, Converage converage, string propertyName)
        {
            StringBuilder builder = new StringBuilder();
            if (string.IsNullOrEmpty(propertyName))
            {
                converage = Converage.Count;
            }
            if (Converage.Avg == converage)
            {
                builder.AppendFormat("select avg({0}) from {1}", EntityTypeCache.GetTableInfo(type).DicColumns[propertyName].Name, EntityTypeCache.GetTableInfo(type).Table.Name);
            }
            else if (Converage.Max == converage)
            {
                builder.AppendFormat("select max({0}) from {1}", EntityTypeCache.GetTableInfo(type).DicColumns[propertyName].Name, EntityTypeCache.GetTableInfo(type).Table.Name);
            }
            else if (Converage.Min == converage)
            {
                builder.AppendFormat("select min({0}) from {1}", EntityTypeCache.GetTableInfo(type).DicColumns[propertyName].Name, EntityTypeCache.GetTableInfo(type).Table.Name);
            }
            else
            {
                builder.AppendFormat("select count(*) from {1}", EntityTypeCache.GetTableInfo(type).DicColumns[propertyName].Name, EntityTypeCache.GetTableInfo(type).Table.Name);
            }
            return builder.ToString();
        }

        public string CreateConverageSql(Type type, Converage converage, string propertyName, IDictionary<string, object> dic, out IDataParameter[] param, ConditionComponent component)
        {
            StringBuilder builder = new StringBuilder();
            if (string.IsNullOrEmpty(propertyName))
            {
                converage = Converage.Count;
            }
            if (Converage.Avg == converage)
            {
                builder.AppendFormat("select avg({0}) from {1} where 1=1 ", EntityTypeCache.GetTableInfo(type).DicColumns[propertyName].Name, EntityTypeCache.GetTableInfo(type).Table.Name);
            }
            else if (Converage.Max == converage)
            {
                builder.AppendFormat("select max({0}) from {1} where 1=1 ", EntityTypeCache.GetTableInfo(type).DicColumns[propertyName].Name, EntityTypeCache.GetTableInfo(type).Table.Name);
            }
            else if (Converage.Min == converage)
            {
                builder.AppendFormat("select min({0}) from {1} where 1=1 ", EntityTypeCache.GetTableInfo(type).DicColumns[propertyName].Name, EntityTypeCache.GetTableInfo(type).Table.Name);
            }
            else
            {
                builder.AppendFormat("select count(*) from {0} where 1=1 ", EntityTypeCache.GetTableInfo(type).Table.Name);
            }
            IList<IDataParameter> source = new List<IDataParameter>();
            foreach (string str in dic.Keys)
            {
                switch (component.DicComponent[str])
                {
                    case SearchComponent.Equals:
                        builder.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, "=", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name);
                        break;

                    case SearchComponent.UnEquals:
                        builder.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, "!=", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name);
                        break;

                    case SearchComponent.Greater:
                        builder.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, ">", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name);
                        break;

                    case SearchComponent.GreaterOrEquals:
                        builder.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, ">=", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name);
                        break;

                    case SearchComponent.Less:
                        builder.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, "<", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name);
                        break;

                    case SearchComponent.LessOrEquals:
                        builder.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, "<=", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name);
                        break;
                }
                source.Add(this.CreateParameter("@" + EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, dic[str]));
            }
            param = source.ToArray<IDataParameter>();
            return builder.ToString();
        }

        public string CreateDeleteSql(IEntity entity, out IDataParameter[] param)
        {
            return this.CreateDeleteSql(entity.GetType(), entity, out param);
        }

        public string CreateDeleteSql(IEntity entity, out IDataParameter[] param, ConditionComponent component)
        {
            if (entity == null)
            {
                throw new NullReferenceException("the delete entity is null");
            }
            IList<IDataParameter> source = new List<IDataParameter>();
            StringBuilder builder = new StringBuilder("");
            StringBuilder builder2 = new StringBuilder("");
            builder.AppendFormat("delete from {0} where 1=1 ", EntityTypeCache.GetTableInfo(entity).Table.Name);
            foreach (string str in component.DicComponent.Keys)
            {
                switch (component.DicComponent[str])
                {
                    case SearchComponent.Equals:
                        builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, "=", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name);
                        break;

                    case SearchComponent.UnEquals:
                        builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, "!=", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name);
                        break;

                    case SearchComponent.Greater:
                        builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, ">", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name);
                        break;

                    case SearchComponent.GreaterOrEquals:
                        builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, ">=", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name);
                        break;

                    case SearchComponent.Less:
                        builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, "<", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name);
                        break;

                    case SearchComponent.LessOrEquals:
                        builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, "<=", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name);
                        break;
                }
                source.Add(this.CreateParameter("@" + EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, EntityFactory.GetPropertyValue(entity, str)));
            }
            param = source.ToArray<IDataParameter>();
            return (builder.ToString() + builder2.ToString());
        }

        public string CreateDeleteSql(IEntity entity, out IDataParameter[] param, string[] propertyNames)
        {
            return this.CreateDeleteSql(entity.GetType(), entity, out param, propertyNames);
        }

        public string CreateDeleteSql(IEntity entity, out IDataParameter[] param, string propertyName)
        {
            if (entity == null)
            {
                throw new NullReferenceException("the delete entity is null");
            }
            if (string.IsNullOrEmpty(propertyName))
            {
                throw new NullReferenceException("this property must not be null");
            }
            return this.CreateDeleteSql(entity, out param, new string[] { propertyName });
        }

        public string CreateDeleteSql(Type type, object value, out IDataParameter[] param)
        {
            if (value == null)
            {
                throw new NullReferenceException("the delete entity is null");
            }
            IDictionary<string, ColumnAttribute> dicColumns = EntityTypeCache.GetTableInfo(type).DicColumns;
            StringBuilder builder = new StringBuilder("");
            StringBuilder builder2 = new StringBuilder("");
            if (dicColumns.Keys.Count <= 0)
            {
                param = null;
                return null;
            }
            builder.AppendFormat("delete from {0} ", EntityTypeCache.GetTableInfo(type).Table.Name);
            IList<IDataParameter> source = new List<IDataParameter>();
            foreach (string str in dicColumns.Keys)
            {
                if (dicColumns[str].IsPrimaryKey)
                {
                    builder2.AppendFormat("where {0}=@{1}", dicColumns[str].Name, dicColumns[str].Name);
                    source.Add(this.CreateParameter("@" + dicColumns[str].Name, EntityFactory.GetPropertyValue(value, str)));
                    break;
                }
            }
            param = source.ToArray<IDataParameter>();
            return (builder.ToString() + builder2.ToString());
        }

        public string CreateDeleteSql(Type type, object value, out IDataParameter[] param, string propertyName)
        {
            return this.CreateDeleteSql(type, value, out param, new string[] { propertyName });
        }

        public string CreateDeleteSql(Type type, object value, out IDataParameter[] param, string[] propertyNames)
        {
            if (value == null)
            {
                throw new NullReferenceException("the delete entity is null");
            }
            if (propertyNames == null)
            {
                throw new NullReferenceException("this property array is null");
            }
            IDictionary<string, ColumnAttribute> dicColumns = EntityTypeCache.GetTableInfo(type).DicColumns;
            StringBuilder builder = new StringBuilder("");
            StringBuilder builder2 = new StringBuilder("");
            if (dicColumns.Keys.Count > 0)
            {
                builder.AppendFormat("delete from {0} ", EntityTypeCache.GetTableInfo(type).Table.Name);
                builder2.AppendFormat(" where 1=1 ", new object[0]);
                IList<IDataParameter> source = new List<IDataParameter>();
                foreach (string str in dicColumns.Keys)
                {
                    if (propertyNames.Contains<string>(str))
                    {
                        builder2.AppendFormat("and {0}=@{1} ", dicColumns[str].Name, dicColumns[str].Name);
                        if (EntityFactory.GetPropertyValue(value, str) == null)
                        {
                            throw new NullReferenceException("this column " + dicColumns[str].Name + " value is null");
                        }
                        source.Add(this.CreateParameter("@" + dicColumns[str].Name, EntityFactory.GetPropertyValue(value, str)));
                    }
                }
                param = source.ToArray<IDataParameter>();
                return (builder.ToString() + builder2.ToString());
            }
            param = null;
            return null;
        }

        public string CreateInsertSql<T>(T t, out IDataParameter[] param) where T: IEntity
        {
            return this.CreateInsertSql(typeof(T), t, out param);
        }

        public string CreateInsertSql(IEntity entity, out IDataParameter[] param)
        {
            return this.CreateInsertSql(entity.GetType(), entity, out param);
        }

        public string CreateInsertSql(Type type, object value, out IDataParameter[] param)
        {
            if (value == null)
            {
                throw new NullReferenceException("the save entity is null");
            }
            StringBuilder builder = new StringBuilder("");
            StringBuilder builder2 = new StringBuilder("");
            IDictionary<string, ColumnAttribute> dicColumns = EntityTypeCache.GetTableInfo(type).DicColumns;
            if (dicColumns.Keys.Count > 0)
            {
                builder.AppendFormat("insert into {0} (", EntityTypeCache.GetTableInfo(type).Table.Name);
                builder2.AppendFormat(" values (", new object[0]);
                IList<IDataParameter> source = new List<IDataParameter>();
                foreach (string str in dicColumns.Keys)
                {
                    if (!dicColumns[str].AutoIncrement)
                    {
                        builder.AppendFormat("{0},", dicColumns[str].Name);
                        builder2.AppendFormat("{0},", "@" + dicColumns[str].Name);
                    }
                    source.Add(this.CreateParameter("@" + str, EntityFactory.GetPropertyValue(value, str)));
                }
                builder.Replace(",", ")", builder.Length - 1, 1);
                builder2.Replace(",", ")", builder2.Length - 1, 1);
                param = source.ToArray<IDataParameter>();
                return (builder.ToString() + builder2.ToString());
            }
            param = null;
            return null;
        }

        public IDataParameter CreateParameter(string name)
        {
            return this.CreateParameter(name, null);
        }

        public IDataParameter CreateParameter(string name, DataType type)
        {
            return new SqlParameter(name, this.ConvertType(type));
        }

        public IDataParameter CreateParameter(string name, object value)
        {
            return new SqlParameter(name, value);
        }

        public IDataParameter CreateParameter(string name, DataType type, int size)
        {
            SqlParameter parameter = new SqlParameter(name, this.ConvertType(type));
            if (size > 0)
            {
                parameter.Size = size;
            }
            return parameter;
        }

        public IDataParameter CreateParameter(string name, DataType type, object value)
        {
            return new SqlParameter(name, this.ConvertType(type)) { Value = value };
        }

        public IDataParameter CreateParameter(string name, DataType type, int size, object value)
        {
            SqlParameter parameter = new SqlParameter(name, this.ConvertType(type));
            if (size > 0)
            {
                parameter.Size = size;
            }
            parameter.Value = value;
            return parameter;
        }

        public string CreateQueryByPropertySql(Type type, IDictionary<string, object> dic, out IDataParameter[] param)
        {
            StringBuilder builder = new StringBuilder();
            IList<IDataParameter> source = new List<IDataParameter>();
            builder.AppendFormat("select * from {0} where 1=1", EntityTypeCache.GetTableInfo(type).Table.Name);
            foreach (string str in dic.Keys)
            {
                builder.AppendFormat(" and {0}=@{1}", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, EntityTypeCache.GetTableInfo(type).DicColumns[str].Name);
                source.Add(this.CreateParameter("@" + EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, dic[str]));
            }
            param = source.ToArray<IDataParameter>();
            return builder.ToString();
        }

        public string CreateQueryByPropertySql(Type type, IDictionary<string, object> dic, out IDataParameter[] param, ConditionComponent component)
        {
            IList<IDataParameter> source = new List<IDataParameter>();
            StringBuilder builder = new StringBuilder("");
            StringBuilder builder2 = new StringBuilder("");
            builder.AppendFormat("select * from {0} where 1=1 ", EntityTypeCache.GetTableInfo(type).Table.Name);
            foreach (string str in dic.Keys)
            {
                switch (component.DicComponent[str])
                {
                    case SearchComponent.Equals:
                        builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, "=", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name);
                        break;

                    case SearchComponent.UnEquals:
                        builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, "!=", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name);
                        break;

                    case SearchComponent.Greater:
                        builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, ">", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name);
                        break;

                    case SearchComponent.GreaterOrEquals:
                        builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, ">=", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name);
                        break;

                    case SearchComponent.Less:
                        builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, "<", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name);
                        break;

                    case SearchComponent.LessOrEquals:
                        builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, "<=", EntityTypeCache.GetTableInfo(type).DicColumns[str].Name);
                        break;
                }
                source.Add(this.CreateParameter("@" + EntityTypeCache.GetTableInfo(type).DicColumns[str].Name, dic[str]));
            }
            param = source.ToArray<IDataParameter>();
            return (builder.ToString() + builder2.ToString());
        }

        public string CreateQueryByPropertySql(Type type, string propertyName, object value, out IDataParameter[] param)
        {
            StringBuilder builder = new StringBuilder();
            IList<IDataParameter> source = new List<IDataParameter>();
            builder.AppendFormat("select * from {0} where {1}=@{2}", EntityTypeCache.GetTableInfo(type).Table.Name, EntityTypeCache.GetTableInfo(type).DicColumns[propertyName].Name, EntityTypeCache.GetTableInfo(type).DicColumns[propertyName].Name);
            source.Add(this.CreateParameter("@" + EntityTypeCache.GetTableInfo(type).DicColumns[propertyName].Name, value));
            param = source.ToArray<IDataParameter>();
            return builder.ToString();
        }

        public string CreateQuerySql(Type type)
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendFormat("select * from {0}", EntityTypeCache.GetTableInfo(type).Table.Name);
            return builder.ToString();
        }

        public string CreateSingleSql(Type entityType)
        {
            StringBuilder builder = new StringBuilder();
            builder.AppendFormat("select * from {0} where {1}=@{2}", EntityTypeCache.GetTableInfo(entityType).Table.Name, EntityTypeCache.GetTableInfo(entityType).Table.PrimaryKeyName, EntityTypeCache.GetTableInfo(entityType).Table.PrimaryKeyName);
            return builder.ToString();
        }

        public string CreateSingleSql(IEntity entity, out IDataParameter[] param)
        {
            if (entity == null)
            {
                throw new NullReferenceException("the entity is null");
            }
            StringBuilder builder = new StringBuilder("");
            builder.AppendFormat("select * from {0} ", EntityTypeCache.GetTableInfo(entity).Table.Name);
            IList<IDataParameter> source = new List<IDataParameter>();
            builder.AppendFormat("where {0}=@{1}", EntityTypeCache.GetTableInfo(entity).Table.PrimaryKeyName, EntityTypeCache.GetTableInfo(entity).Table.PrimaryKeyName);
            source.Add(this.CreateParameter("@" + EntityTypeCache.GetTableInfo(entity).Table.PrimaryKeyName, EntityFactory.GetPropertyValue(entity, EntityTypeCache.GetTableInfo(entity).Table.PrimaryKeyName)));
            param = source.ToArray<IDataParameter>();
            return builder.ToString();
        }

        public string CreateSingleSql(IEntity entity, out IDataParameter[] param, string[] propertyNames)
        {
            return this.CreateSingleSql(entity.GetType(), entity, out param, propertyNames);
        }

        public string CreateSingleSql(Type type, object pkPropertyValue, out IDataParameter[] param)
        {
            IList<IDataParameter> source = new List<IDataParameter>();
            StringBuilder builder = new StringBuilder();
            builder.AppendFormat("select * from {0} where {1}=@{2}", EntityTypeCache.GetTableInfo(type).Table.Name, EntityTypeCache.GetTableInfo(type).Table.PrimaryKeyName, EntityTypeCache.GetTableInfo(type).Table.PrimaryKeyName);
            source.Add(this.CreateParameter("@" + EntityTypeCache.GetTableInfo(type).Table.PrimaryKeyName, pkPropertyValue));
            param = source.ToArray<IDataParameter>();
            return builder.ToString();
        }

        public string CreateSingleSql(Type type, object value, out IDataParameter[] param, string[] propertyNames)
        {
            if (value == null)
            {
                throw new NullReferenceException("the entity is null");
            }
            IList<IDataParameter> source = new List<IDataParameter>();
            StringBuilder builder = new StringBuilder("");
            builder.AppendFormat("select * from {0} ", EntityTypeCache.GetTableInfo(type).Table.Name);
            builder.AppendFormat("where ", new object[0]);
            foreach (string str in propertyNames)
            {
                builder.AppendFormat("{0}=@{1} and ", EntityTypeCache.GetTableInfo(type).DicProperties[str].Name, EntityTypeCache.GetTableInfo(type).DicProperties[str].Name);
                if (EntityFactory.GetPropertyValue(value, str) == null)
                {
                    throw new NullReferenceException("this column " + EntityTypeCache.GetTableInfo(type).DicProperties[str].Name + " value is null");
                }
                source.Add(this.CreateParameter("@" + EntityTypeCache.GetTableInfo(type).DicProperties[str].Name, EntityFactory.GetPropertyValue(value, str)));
            }
            builder.Remove(builder.Length - 4, 4);
            param = source.ToArray<IDataParameter>();
            return builder.ToString();
        }

        public string CreateUpdateSql(IEntity entity, out IDataParameter[] param)
        {
            return this.CreateUpdateSql(entity.GetType(), entity, out param);
        }

        public string CreateUpdateSql(IEntity entity, out IDataParameter[] param, ConditionComponent component)
        {
            StringBuilder builder = new StringBuilder("");
            StringBuilder builder2 = new StringBuilder("");
            IList<IDataParameter> source = new List<IDataParameter>();
            builder.AppendFormat("update {0} set ", EntityTypeCache.GetTableInfo(entity).Table.Name);
            builder2.Append(" where 1=1 ");
            foreach (string str in EntityTypeCache.GetTableInfo(entity).DicProperties.Keys)
            {
                if (component.DicComponent.Keys.Contains(str))
                {
                    switch (component.DicComponent[str])
                    {
                        case SearchComponent.Equals:
                            builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, "=", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name);
                            break;

                        case SearchComponent.UnEquals:
                            builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, "!=", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name);
                            break;

                        case SearchComponent.Greater:
                            builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, ">", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name);
                            break;

                        case SearchComponent.GreaterOrEquals:
                            builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, ">=", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name);
                            break;

                        case SearchComponent.Less:
                            builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, "<", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name);
                            break;

                        case SearchComponent.LessOrEquals:
                            builder2.AppendFormat("and {0}{1}@{2} ", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, "<=", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name);
                            break;
                    }
                    source.Add(this.CreateParameter("@" + EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, EntityFactory.GetPropertyValue(entity, str)));
                }
                else if ((!EntityTypeCache.GetTableInfo(entity).DicColumns[str].IsPrimaryKey && !EntityTypeCache.GetTableInfo(entity).DicColumns[str].IsUnique) && !EntityTypeCache.GetTableInfo(entity).DicColumns[str].AutoIncrement)
                {
                    builder.AppendFormat("{0}=@{1},", EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name);
                    source.Add(this.CreateParameter("@" + EntityTypeCache.GetTableInfo(entity).DicColumns[str].Name, EntityFactory.GetPropertyValue(entity, str)));
                }
            }
            builder.Remove(builder.Length - 1, 1);
            param = source.ToArray<IDataParameter>();
            return (builder.ToString() + builder2.ToString());
        }

        public string CreateUpdateSql(IEntity entity, out IDataParameter[] param, string[] propertyNames)
        {
            return this.CreateUpdateSql(entity.GetType(), entity, out param, propertyNames);
        }

        public string CreateUpdateSql(IEntity entity, out IDataParameter[] param, string propertyName)
        {
            if (entity == null)
            {
                throw new NullReferenceException("the update entity is null");
            }
            if (string.IsNullOrEmpty(propertyName))
            {
                throw new NullReferenceException("this property must not be null");
            }
            if (!EntityTypeCache.GetTableInfo(entity).DicColumns.Keys.Contains(propertyName))
            {
                throw new Exception("this entity do not contain the property:" + propertyName);
            }
            return this.CreateUpdateSql(entity, out param, new string[] { propertyName });
        }

        public string CreateUpdateSql(Type type, object value, out IDataParameter[] param)
        {
            if (value == null)
            {
                throw new NullReferenceException("the update entity is null");
            }
            StringBuilder builder = new StringBuilder("");
            StringBuilder builder2 = new StringBuilder("");
            IDictionary<string, ColumnAttribute> dicColumns = EntityTypeCache.GetTableInfo(type).DicColumns;
            if (dicColumns.Keys.Count > 0)
            {
                builder.AppendFormat("update {0} set ", EntityTypeCache.GetTableInfo(type).Table.Name);
                builder2.AppendFormat(" where ", new object[0]);
                IList<IDataParameter> source = new List<IDataParameter>();
                foreach (string str in dicColumns.Keys)
                {
                    if (dicColumns[str].IsPrimaryKey)
                    {
                        builder2.AppendFormat("{0}=@{1}", dicColumns[str].Name, dicColumns[str].Name);
                        source.Add(this.CreateParameter("@" + dicColumns[str].Name, EntityFactory.GetPropertyValue(value, str)));
                    }
                    else if ((!dicColumns[str].IsPrimaryKey && !dicColumns[str].IsUnique) && !dicColumns[str].AutoIncrement)
                    {
                        builder.AppendFormat("{0}=@{1},", dicColumns[str].Name, dicColumns[str].Name);
                        source.Add(this.CreateParameter("@" + dicColumns[str].Name, EntityFactory.GetPropertyValue(value, str)));
                    }
                }
                builder.Remove(builder.Length - 1, 1);
                param = source.ToArray<IDataParameter>();
                return (builder.ToString() + builder2.ToString());
            }
            param = null;
            return null;
        }

        public string CreateUpdateSql(Type type, object value, out IDataParameter[] param, string propertyName)
        {
            if (value == null)
            {
                throw new NullReferenceException("the update entity is null");
            }
            if (string.IsNullOrEmpty(propertyName))
            {
                throw new NullReferenceException("this property must not be null");
            }
            if (!EntityTypeCache.GetTableInfo(type).DicColumns.Keys.Contains(propertyName))
            {
                throw new Exception("this entity do not contain the property:" + propertyName);
            }
            return this.CreateUpdateSql(type, value, out param, new string[] { propertyName });
        }

        public string CreateUpdateSql(Type type, object value, out IDataParameter[] param, string[] propertyNames)
        {
            if (value == null)
            {
                throw new NullReferenceException("the update entity is null");
            }
            if (propertyNames == null)
            {
                throw new NullReferenceException("this property array is null");
            }
            IDictionary<string, ColumnAttribute> dicColumns = EntityTypeCache.GetTableInfo(type).DicColumns;
            StringBuilder builder = new StringBuilder("");
            StringBuilder builder2 = new StringBuilder("");
            if (dicColumns.Keys.Count > 0)
            {
                builder.AppendFormat("update {0} set ", EntityTypeCache.GetTableInfo(type).Table.Name);
                builder2.AppendFormat(" where 1=1 ", new object[0]);
                IList<IDataParameter> source = new List<IDataParameter>();
                foreach (string str in dicColumns.Keys)
                {
                    if (propertyNames.Contains<string>(str))
                    {
                        builder2.AppendFormat("and {0}={1} ", dicColumns[str].Name, "@" + dicColumns[str].Name);
                        source.Add(this.CreateParameter("@" + dicColumns[str].Name, EntityFactory.GetPropertyValue(value, str)));
                    }
                    else if ((!dicColumns[str].IsPrimaryKey && !dicColumns[str].IsUnique) && !dicColumns[str].AutoIncrement)
                    {
                        builder.AppendFormat("{0}={1},", dicColumns[str].Name, "@" + dicColumns[str].Name);
                        source.Add(this.CreateParameter("@" + dicColumns[str].Name, EntityFactory.GetPropertyValue(value, str)));
                    }
                }
                builder.Remove(builder.Length - 1, 1);
                param = source.ToArray<IDataParameter>();
                return (builder.ToString() + builder2.ToString());
            }
            param = null;
            return null;
        }

        public void Dispose()
        {
            GC.SuppressFinalize(this);
        }
    }
}

